package name.marz.to.go.ahg;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.util.logging.Level;
import java.util.logging.Logger;

import name.marz.to.go.ahg.SMBC.executer.SMBCLoginExecuter;
import name.marz.to.go.ahg.SMBC.executer.SMBCTopPageExecuter;
import name.marz.to.go.ahg.common.cli.OutFileOption;
import name.marz.to.go.ahg.common.util.HttpUtil;
import name.marz.to.go.ahg.common.util.LogUtil;
import name.marz.to.go.ahg.core.AbstractAutoGetterMain;
import name.marz.to.go.ahg.core.AutoGetterHttpClient;
import name.marz.to.go.ahg.core.Parameters;
import name.marz.to.go.ahg.core.exception.InvalidDocumentException;
import name.marz.to.go.ahg.core.exception.UserProcessException;
import name.marz.to.go.ahg.core.executer.AbstractExecuter;
import name.marz.to.go.ahg.core.executer.AbstractLoginExecuter;
import name.marz.to.go.ahg.core.executer.DocumentGetExecuter;
import name.marz.to.go.ahg.core.executer.Executer;
import name.marz.to.go.ahg.core.executer.FileDownloadExecuter;
import name.marz.to.go.ahg.core.responsehandler.NopResponseHandler;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;


public class SMBCAccountGetMain extends AbstractAutoGetterMain {
	private static final Logger log = Logger.getLogger(SMBCAccountGetMain.class.getName());
	private static final String DEFAULT_MEISAI_FILENAME="meisai.csv";
	private final AutoGetterHttpClient client = new AutoGetterHttpClient();
	
	private String userName1;
	private String userName2;
	private String password;
	private String accountNum;
	private File outFile;

	/**
	 * 
	 */
	public SMBCAccountGetMain() {
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		SMBCAccountGetMain main = new SMBCAccountGetMain();
		main.Main(args);
	}
	
	@Override
	protected void finish() {
		// 終了処理
		client.getConnectionManager().shutdown();
	}

	@Override
	public Document goTopPage() throws ClientProtocolException, IOException {
		final String host = "https://direct.smbc.co.jp";
		SMBCTopPageExecuter executer = new SMBCTopPageExecuter(host,"/aib/aibgsjsw5001.jsp" , client);
		return executer.execute();
	}

	@Override
	public Document doLogin(Document doc) throws ClientProtocolException, IOException,UserProcessException {
		Parameters p = HttpUtil.getParametersFromFormTag(doc, "Login");
		LogUtil.log(Level.FINE,p,"top page parameters");
		final URI uri = HttpUtil.createURISafety(p.get("domainSumitomo"));
		AbstractLoginExecuter executer = new SMBCLoginExecuter(uri, client, p);
		
		executer.setUserIdentifiers(new String[] {userName1,userName2});
		executer.setUserPass(password);
		
		return executer.execute();
	}

	@Override
	public Document goDownloadPage(Document doc) throws ClientProtocolException, IOException  {
		String accountNumPattern = ".*"+accountNum+".*";
		// 口座の詳細ページへのURLを取得
		Element top_e = doc.getElementById("top-02");
		if ( top_e == null ) throw new InvalidDocumentException("id not found top-02",doc);
		Element e2 = top_e.getElementsByClass("dataTable").first();
		if ( e2 == null ) throw new InvalidDocumentException("class dataTable not found",doc);
		Elements anchors = e2.getElementsByTag("a");
		
		String href = null;
		for (Element e : anchors) {
			if ( e.text().matches(accountNumPattern) ) {
				href = e.attr("href");
				break;
			}
		}
		if ( href == null ) throw new IllegalArgumentException("account num pattern not found : "+accountNumPattern);
		final URI uri = HttpUtil.createURISafety(href);
		
		DocumentGetExecuter executer = new DocumentGetExecuter(uri, client,"口座明細");
		return executer.execute();
	}

	@Override
	public File doDownload(Document doc)  throws ClientProtocolException, IOException, UserProcessException {
		final String host = "https://direct3.smbc.co.jp";
		final URI uri = HttpUtil.createURISafety(host, "/servlet/com.smbc.CsvServlet?CsvTrxID=SUP0112");
		FileDownloadExecuter executer = new FileDownloadExecuter(uri, client, outFile);
		executer.execute();
		return outFile;
	}

	@Override
	public void doLogout(Document doc)  throws ClientProtocolException, IOException, UserProcessException {
		String href;
		// ログアウト用URLの取得1
		final String LOGOUT_STR="ログアウト";
		Elements es = doc.getElementsMatchingOwnText(LOGOUT_STR);
		if ( es.isEmpty()) throw new InvalidDocumentException(LOGOUT_STR+"の文字列が、見つかりません",doc);
		log.fine("logout html="+es.first());
		href = es.first().attr("href");
		if ( href.length() == 0 ) throw new InvalidDocumentException("ログアウト用のhrefが見つかりません",doc);
		final URI uri = HttpUtil.createURISafety(href);
		log.fine("logout uri="+uri);
		Executer<Object> executer = new AbstractExecuter<Object>(uri, client,"ログアウト") {
			@Override
			public Object execute() throws ClientProtocolException,IOException, UserProcessException {
				HttpUriRequest req = new HttpGet(uri);
				ResponseHandler<Object> handler = new NopResponseHandler();
				log.info(pageName+" ページ処理中 ... " + req.getURI());
				LogUtil.log(Level.FINE,req.getAllHeaders(),"request header");
				return client.execute(req, handler);
			}
			
		};
		executer.execute();
	}

	@SuppressWarnings("static-access")
	@Override
	protected Options getOptions() {
		Options options = new Options();
		options.addOption(new OutFileOption(false));
		options.addOption(OptionBuilder.hasArg(true).withArgName("user1")
				.isRequired(true).withDescription("ユーザー名1")
				.create("user1"));
		options.addOption(OptionBuilder.hasArg(true).withArgName("user2")
				.isRequired(true).withDescription("ユーザー名2")
				.create("user2"));
		options.addOption(OptionBuilder.hasArg(true).withArgName("password")
				.isRequired(true).withDescription("第1暗証")
				.create("password"));
		options.addOption(OptionBuilder.hasArg(true).withArgName("account no")
				.isRequired(true).withDescription("口座番号")
				.create("account"));
		return options;
	}

	@Override
	protected void setParams(CommandLine cmd) {
		userName1 = cmd.getOptionValue("user1");
		userName2 = cmd.getOptionValue("user2");
		password = cmd.getOptionValue("password");
		accountNum = cmd.getOptionValue("account");
		outFile = new File(cmd.getOptionValue("out", DEFAULT_MEISAI_FILENAME));
	}
}
